package com.bluelinelabs.logansquare.processor.processor;

import static javax.tools.Diagnostic.Kind.ERROR;

import com.bluelinelabs.logansquare.processor.JsonObjectHolder;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * Processor
 */
public abstract class Processor {
    /**
     * mProcessingEnv
     */
    protected ProcessingEnvironment mProcessingEnv;

    /**
     * Processor
     * @param processingEnv processingEnv
     */
    protected Processor(ProcessingEnvironment processingEnv) {
        mProcessingEnv = processingEnv;
    }

    /**
     * getAnnotation
     * @return Class
     */
    public abstract Class getAnnotation();

    /**
     * findAndParseObjects
     * @param env env
     * @param jsonObjectMap jsonObjectMap
     * @param elements elements
     * @param types types
     */
    public abstract void findAndParseObjects(
            RoundEnvironment env, Map<String, JsonObjectHolder> jsonObjectMap, Elements elements, Types types);

    /**
     * allProcessors
     * @param processingEnvironment processingEnvironment
     * @return List
     */
    public static List<Processor> allProcessors(ProcessingEnvironment processingEnvironment) {
        List<Processor> list = new ArrayList<>();
        list.add(new JsonObjectProcessor(processingEnvironment));
        list.add(new OnJsonParseCompleteProcessor(processingEnvironment));
        list.add(new OnPreSerializeProcessor(processingEnvironment));
        list.add(new JsonFieldProcessor(processingEnvironment));
        return list;
    }

    /**
     * error
     * @param element element
     * @param message message
     * @param args args
     */
    public void error(Element element, String message, Object... args) {
        mProcessingEnv.getMessager().printMessage(ERROR, String.format(message, args), element);
    }
}
